﻿using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;

namespace PRWPF
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        private System.Windows.Forms.FolderBrowserDialog fbd;
        private List<FileInfo> dupFiles = null;

        public MainWindow()
        {
            this.fbd = new System.Windows.Forms.FolderBrowserDialog();
            InitializeComponent();
            FolderFileHelper.DebugOutput += FolderFileHelper_DebugOutput;
        }

        private void FolderFileHelper_DebugOutput(string DebugMessage)
        {
            this.Dispatcher.Invoke((System.Action)delegate() { this.Output.AppendText(DebugMessage + "\r\n"); this.Output.ScrollToEnd(); });
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.Output.Clear();
        }

        private void CheckBox_Checked(object sender, RoutedEventArgs e)
        {
            this.ReoTo.IsEnabled = false;
        }

        private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
        {
            this.ReoTo.IsEnabled = true;
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            this.setDateRenameTemplate.Text = Properties.Settings.Default.DateFormat;
            this.setExifRenameTemplate.Text = Properties.Settings.Default.ExifFormat;
            this.setDigitDataSplitCount.Text = Properties.Settings.Default.DigitDataSplitCount.ToString();
            this.setDigitDataLimitMB.Text = Properties.Settings.Default.DigitDataLimitMB.ToString();
            this.setSimpleDigitDataqLimitMB.Text = Properties.Settings.Default.SimpleDigitDataqLimitMB.ToString();
        }

        private void setSave_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Properties.Settings.Default.DateFormat = this.setDateRenameTemplate.Text.Trim();
                Properties.Settings.Default.ExifFormat = this.setExifRenameTemplate.Text.Trim();
                Properties.Settings.Default.DigitDataSplitCount = int.Parse(this.setDigitDataSplitCount.Text.Trim());
                Properties.Settings.Default.DigitDataLimitMB = double.Parse(this.setDigitDataLimitMB.Text.Trim());
                Properties.Settings.Default.SimpleDigitDataqLimitMB = double.Parse(this.setSimpleDigitDataqLimitMB.Text.Trim());
                Properties.Settings.Default.Save();
            }
            catch (System.Exception ex)
            {
                MessageBox.Show("保存设置失败，请检查输入合法性：" + ex.Message);
            }
        }

        private void ReoFrom_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (this.fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.ReoFrom.Text = this.fbd.SelectedPath;
            }
        }

        private void ReoTo_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (this.fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.ReoTo.Text = this.fbd.SelectedPath;
            }
        }

        private void ReoStart_Click(object sender, RoutedEventArgs e)
        {
        }

        private void ReoStop_Click(object sender, RoutedEventArgs e)
        {
            FolderFileHelper.ThingsCanGoOn = false;
        }

        private void DupBaseDirOnly_Checked(object sender, RoutedEventArgs e)
        {
            this.DupComDir.IsEnabled = false;
        }

        private void DupBaseDirOnly_Unchecked(object sender, RoutedEventArgs e)
        {
            this.DupComDir.IsEnabled = true;
        }

        private void DupBaseDir_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (this.fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.DupBaseDir.Text = this.fbd.SelectedPath;
            }
        }

        private void DupComDir_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (this.fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.DupComDir.Text = this.fbd.SelectedPath;
            }
        }

        private void DupStart_Click(object sender, RoutedEventArgs e)
        {
            Thread t = new System.Threading.Thread(new ParameterizedThreadStart(this.StartDupProcess));
            if (!FolderFileHelper.ThingsCanGoOn)
            {
                this.DupBaseFound.Content = "0";
                this.DupBaseLoad.Content = "0";
                this.DupBaseDup.Content = "0";
                this.DupCompFound.Content = "0";
                this.DupCompDup.Content = "0";
                this.DupCompLoad.Content = "0";
                this.DupTotalDup.Content = "0";
                dynamic param = new
                {
                    StartFolder = this.DupBaseDir.Text,
                    CompareFolder = this.DupComDir.Text,
                    IsBaseDirOnly = this.DupBaseDirOnly.IsChecked.Value || this.DupComDir.Text.Trim() == string.Empty,
                    IsSimple = this.DupSimple.IsChecked == true
                };
                t.Start(param);
            }
            else
            {
                MessageBox.Show("已经有任务在进行中");
            }
        }

        private void StartDupProcess(dynamic Param)
        {
            FolderFileHelper.ThingsCanGoOn = true;

            int dupBaseFound = 0;
            List<FileInfo> dupBaseFiles = FolderFileHelper.GetDirectoryFiles(
                (string)Param.StartFolder,
                null,
                delegate(int fc)
                {
                    dupBaseFound += fc;
                    this.Dispatcher.Invoke(
                        (System.Action)delegate()
                        {
                            this.DupBaseFound.Content = dupBaseFound.ToString();
                        });
                });

            List<FileInfo> dupCompFiles = null;
            if (!(bool)Param.IsBaseDirOnly)
            {
                int dupCompFound = 0;
                dupCompFiles = FolderFileHelper.GetDirectoryFiles(
                (string)Param.CompareFolder,
                null,
                delegate(int fc)
                {
                    dupCompFound += fc;
                    this.Dispatcher.Invoke(
                        (System.Action)delegate()
                        {
                            this.DupCompFound.Content = dupCompFound.ToString();
                        });
                });
            }

            int dupBaseLoad = 0;
            int dupBaseCount = 0;
            var digitsBase = FolderFileHelper.GetFileDigits(dupBaseFiles,
                delegate(string fn, FileProcessResult r)
                {
                    this.Dispatcher.Invoke(
                        (System.Action)delegate()
                        {
                            this.DupCurFile.Content = fn;
                        });
                    switch (r)
                    {
                        case FileProcessResult.HashBuildSucceed:
                            dupBaseLoad++;
                            this.Dispatcher.Invoke(
                                (System.Action)delegate()
                                {
                                    this.DupBaseLoad.Content = dupBaseLoad.ToString();
                                });
                            break;

                        case FileProcessResult.FileReadFail:
                            break;

                        case FileProcessResult.DuplicateFound:
                            dupBaseCount++;
                            this.Dispatcher.Invoke(
                                (System.Action)delegate()
                                {
                                    this.DupBaseDup.Content = dupBaseCount.ToString();
                                });
                            break;

                        default:
                            break;
                    }
                },
                (bool)Param.IsSimple
            );

            Dictionary<string, List<FileInfo>> digitsComp = null;
            if (!(bool)Param.IsBaseDirOnly)
            {
                int dupCompLoad = 0;
                int dupCompCount = 0;
                digitsComp = FolderFileHelper.GetFileDigits(dupCompFiles,
                    delegate(string fn, FileProcessResult r)
                    {
                        this.Dispatcher.Invoke(
                            (System.Action)delegate()
                            {
                                this.DupCurFile.Content = fn;
                            });
                        switch (r)
                        {
                            case FileProcessResult.HashBuildSucceed:
                                dupCompLoad++;
                                this.Dispatcher.Invoke(
                                    (System.Action)delegate()
                                    {
                                        this.DupCompLoad.Content = dupCompLoad.ToString();
                                    });
                                break;

                            case FileProcessResult.FileReadFail:
                                break;

                            case FileProcessResult.DuplicateFound:
                                dupCompCount++;
                                this.Dispatcher.Invoke(
                                    (System.Action)delegate()
                                    {
                                        this.DupCompDup.Content = dupCompCount.ToString();
                                    });
                                break;

                            default:
                                break;
                        }
                    },
                    (bool)Param.IsSimple
                );
            }

            List<FileInfo> dupFiles = null;
            if (!(bool)Param.IsBaseDirOnly)
            {
                dupFiles = digitsComp.Where(c => digitsBase.ContainsKey(c.Key)).Aggregate(new List<FileInfo>(), (val, next) => val.Concat(next.Value).ToList());
                this.Dispatcher.Invoke(
                    (System.Action)delegate()
                    {
                        this.DupTotalDup.Content = dupFiles.Count.ToString();
                    });
                this.FolderFileHelper_DebugOutput(dupFiles.Aggregate("", (val, next) => val + "\r\n重复的文件：" + next.FullName));
            }
            else
            {
                dupFiles = digitsBase.Aggregate(new List<FileInfo>(), (val, next) => val.Concat(next.Value.Skip(1)).ToList());
            }
            this.dupFiles = dupFiles;

            FolderFileHelper.ThingsCanGoOn = false;
        }

        private void DupDelete_Click(object sender, RoutedEventArgs e)
        {
            Thread t = new System.Threading.Thread(new ThreadStart(this.StartDeleteDupFiles));
            if (!FolderFileHelper.ThingsCanGoOn)
            {
                t.Start();
            }
            else
            {
                MessageBox.Show("已经有任务在进行中");
            }
        }

        private void StartDeleteDupFiles()
        {
            FolderFileHelper.ThingsCanGoOn = true;

            if (this.dupFiles != null)
            {
                lock (this.dupFiles)
                {
                    foreach (var fi in this.dupFiles)
                    {
                        try
                        {
                            fi.Delete();
                            this.Dispatcher.Invoke(
                                (System.Action)delegate()
                                {
                                    this.FolderFileHelper_DebugOutput("已删除文件：" + fi.FullName);
                                });
                        }
                        catch (System.Exception ex)
                        {
                            this.Dispatcher.Invoke(
                                (System.Action)delegate()
                                {
                                    this.FolderFileHelper_DebugOutput("删除文件失败：" + fi.FullName + " " + ex.Message);
                                });
                        }
                        finally
                        {
                            this.Dispatcher.Invoke(
                                (System.Action)delegate()
                                {
                                    this.DupCurFile.Content = fi.FullName;
                                });
                        }
                    }
                    dupFiles = null;
                }
            }
            else
            {
                this.Dispatcher.Invoke(
                    (System.Action)delegate()
                    {
                        MessageBox.Show("还没有对比重复的文件唉……");
                    });
            }

            FolderFileHelper.ThingsCanGoOn = false;
        }
    }
}